package com.jindy.module.logisticscost.service.impl;

import com.jindy.common.core.domain.entity.SysUser;
import com.jindy.common.core.domain.model.LoginUser;
import com.jindy.common.exception.base.BaseException;
import com.jindy.common.utils.DateUtils;
import com.jindy.common.utils.SecurityUtils;
import com.jindy.jpush.domain.UniPushDomain;
import com.jindy.jpush.utils.UniJpushUtils;
import com.jindy.module.approvalConfig.domain.ApprovalConfig;
import com.jindy.module.approvalConfig.mapper.ApprovalConfigMapper;
import com.jindy.module.jpush.mapper.JpushMapper;
import com.jindy.module.logisticscost.domain.LogisticsCost;
import com.jindy.module.logisticscost.domain.LogisticsProduct;
import com.jindy.module.logisticscost.mapper.LogisticsCostMapper;
import com.jindy.module.logisticscost.mapper.LogisticsProductMapper;
import com.jindy.module.logisticscost.service.LogisticsCostService;
import com.jindy.module.order.domain.Order;
import com.jindy.module.order.domain.OrderProduct;
import com.jindy.module.order.mapper.OrderMapper;
import com.jindy.module.order.mapper.OrderProductMapper;
import com.jindy.module.order.service.impl.OrderServiceImpl;
import com.jindy.module.outboundorder.domain.OutboundOrder;
import com.jindy.module.outboundorder.domain.OutboundOrderMachine;
import com.jindy.module.outboundorder.mapper.OutboundOrderMachineMapper;
import com.jindy.module.outboundorder.mapper.OutboundOrderMapper;
import com.jindy.module.returnapplyorder.domain.ReturnApply;
import com.jindy.module.returnapplyorder.domain.ReturnApplyProduct;
import com.jindy.module.returnapplyorder.dto.ReturnApplyDto;
import com.jindy.module.returnapplyorder.mapper.ReturnApplyMapper;
import com.jindy.module.returnapplyorder.mapper.ReturnApplyProductMapper;
import com.jindy.module.transfer.domain.SyTransferT;
import com.jindy.module.transfer.mapper.SyTransferTMapper;
import com.jindy.module.transferProduct.domain.SyTransferProductT;
import com.jindy.module.transferProduct.mapper.SyTransferProductTMapper;
import com.jindy.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 物流费用Service业务实现类
 *
 * @author zhaoxi
 * @date 2022-11-12
 */
@Service
public class LogisticsCostServiceImpl implements LogisticsCostService {
    private static final Logger LOGGER = LoggerFactory.getLogger(LogisticsCostServiceImpl.class);

    @Resource
    private LogisticsCostMapper logisticsCostMapper;

    @Resource
    private OutboundOrderMapper outboundOrderMapper;

    @Resource
    private ReturnApplyMapper returnApplyMapper;

    @Resource
    private ReturnApplyProductMapper returnApplyProductMapper;

    @Autowired
    private ISysUserService sysUserService;

    @Resource
    private OutboundOrderMachineMapper outboundOrderMachineMapper;

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private OrderProductMapper orderProductMapper;

    @Resource
    private LogisticsProductMapper logisticsProductMapper;

    @Resource
    private SyTransferTMapper syTransferTMapper;
    @Resource
    private SyTransferProductTMapper syTransferProductMapper;

    /**
     * 消息推送设备信息
     */
    @Resource
    private JpushMapper jpushMapper;

    /**
     * 租赁订单服务实现类
     */
    @Autowired
    private OrderServiceImpl orderServiceImpl;

    /**
     * 配置信息表
     */
    @Resource
    private ApprovalConfigMapper approvalConfigMapper;

    /**
     * 查询物流费用列表
     *
     * @param cost 物流费用
     * @return 物流费用列表
     */
    @Override
    public List<LogisticsCost> selectLogisticsCostList(LogisticsCost cost) {
        //获取当前登录人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (Objects.isNull(loginUser)){
            throw new BaseException("查询【物流管理】列表-请先登录");
        }
        Long loginUserUserId = loginUser.getUserId();

        //王秋月可见所有数据
        List<ApprovalConfig> approvalConfigList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("Wl_ADMIN", "1"));
        if (CollectionUtils.isEmpty(approvalConfigList)){
            throw new BaseException("查询【物流管理】列表-请检查配置：Wl_ADMIN");
        }
        List<Long> collect = approvalConfigList.stream().map(ApprovalConfig::getUserId).collect(Collectors.toList());
        if (loginUserUserId.equals(1L) || collect.contains(loginUserUserId)){
            loginUserUserId=null;
        }
        List<LogisticsCost> list = logisticsCostMapper.selectLogisticsCostAuthorityList(cost, loginUserUserId);
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(logisticsCost -> {
                // 查询物流产品
                setLogisticsProductList(logisticsCost);
            });
        }
        return list;
    }

    /**
     * 查询物流费用
     *
     * @param id 物流费用主键
     * @return 物流费用数据
     */
    @Override
    public LogisticsCost selectLogisticsCostById(String id) {
        LogisticsCost cost = logisticsCostMapper.selectLogisticsCostById(id);
        // 查询物流产品
        setLogisticsProductList(cost);
        return cost;
    }


    /**
     * 查询物流产品
     *
     * @param cost
     */
    void setLogisticsProductList(LogisticsCost cost) {
        LogisticsProduct logisticsProduct = new LogisticsProduct();
        logisticsProduct.setLogisticsId(cost.getId());
        List<LogisticsProduct> list = logisticsProductMapper.selectLogisticsProductList(logisticsProduct);
        if (!CollectionUtils.isEmpty(list)) {
            cost.setLogisticsProductList(list);
        }
    }


    /**
     * 新增物流费用数据
     *
     * @param cost 物流费用
     * @return 物流费用
     */
    @Override
    //    @Transactional(rollbackFor = Exception.class)
    public int insertLogisticsCost(LogisticsCost cost) {
        SysUser sysUser = sysUserService.selectUserByUserName(SecurityUtils.getUsername());
        cost.setCreateBy(sysUser.getUserName());
        cost.setCreateTime(DateUtils.getNowDate());

        int result = logisticsCostMapper.insertLogisticsCost(cost);
        if (result > 0) {
            // 出库物流
            if (cost.getOrderProperty() != null && !cost.getOrderProperty().equals("")) {
                if (cost.getOrderProperty().equals("1")) {
                    // 查出插入的这条数据
                    LogisticsCost logisticsCost = new LogisticsCost();
                    logisticsCost.setOutboundNo(cost.getOutboundNo());
                    List<LogisticsCost> logisticsCostList = logisticsCostMapper.selectLogisticsCostList(logisticsCost);
                    if (!CollectionUtils.isEmpty(logisticsCostList)) {
                        LogisticsCost logisticsCost1 = logisticsCostList.get(0);
                        if (!CollectionUtils.isEmpty(cost.getLogisticsProductList())) {
                            // 物流增加物流产品
                            cost.getLogisticsProductList().forEach(product -> {
                                product.setLogisticsId(logisticsCost1.getId());
                                product.setOrderProperty(logisticsCost1.getOrderProperty());
                                logisticsProductMapper.insertLogisticsProduct(product);
                            });
                        }
                        // 根据orderNo校验更改父单物流状态（先填物流，再填出库单）
                        checkLogisticsStatus2(cost);

                        // 如果填了物流到达时间，则出库机器加物流到达时间
                        if (cost.getArrivalDate() != null) {
                            updateOutMachineTime(cost);
                        }
                    }// 回货申请物流
                } else if (cost.getOrderProperty().equals("2")) {

                    // 把物流费用加到对应的入库申请单子单中
                    // updateReturnApply(cost);

                    // 判断出库单子单是否已填完物流费用，并给父入库申请单添加相应的状态
                    // updateReturnApplyStatus(cost);

                    // 查出插入的这条数据
                    LogisticsCost logisticsCost = new LogisticsCost();
                    logisticsCost.setReturnApplyNo(cost.getReturnApplyNo());
                    List<LogisticsCost> logisticsCostList = logisticsCostMapper.selectLogisticsCostList(logisticsCost);
                    if (!CollectionUtils.isEmpty(logisticsCostList)) {
                        LogisticsCost logisticsCost1 = logisticsCostList.get(0);// 倒序查询，新增的物流在第一条
                        if (!CollectionUtils.isEmpty(cost.getLogisticsProductList())) {
                            // 物流增加物流产品
                            cost.getLogisticsProductList().forEach(product -> {
                                product.setLogisticsId(logisticsCost1.getId());
                                product.setOrderProperty(logisticsCost1.getOrderProperty());
                                logisticsProductMapper.insertLogisticsProduct(product);
                            });
                        }
                    }
                    // 校验产品数量，更改回库申请单和子单父单物流状态
                    checkReturnApplyStatus2(cost);
                }// 库存调拨物流
                else {
                    if ((cost.getOrderProperty().equals("3"))) {
                        // 查出插入的这条数据
                        LogisticsCost logisticsCost = new LogisticsCost();
                        logisticsCost.setOrderId(cost.getOrderId());
                        logisticsCost.setOrderProperty("3");
                        List<LogisticsCost> logisticsCostList = logisticsCostMapper.selectLogisticsCostList(logisticsCost);
                        if (!CollectionUtils.isEmpty(logisticsCostList)) {
                            LogisticsCost logisticsCost1 = logisticsCostList.get(0);
                            if (!CollectionUtils.isEmpty(cost.getLogisticsProductList())) {
                                // 物流增加物流产品
                                cost.getLogisticsProductList().forEach(product -> {
                                    product.setLogisticsId(logisticsCost1.getId());
                                    product.setOrderProperty(logisticsCost1.getOrderProperty());
                                    logisticsProductMapper.insertLogisticsProduct(product);
                                });
                            }
                        }
                        // 校验产品数量，更改回库申请单和子单父单物流状态
                        checkTransferStatus(cost);
                    }
                }
            }
            //  回货物流填写完成通知业务人员
            if ("2".equals(cost.getOrderProperty())) {
                noticeInitiator(cost.getOrderNo(),cost.getOrderNo() + "入库物流填写完成！");
            }
            // 填写完入库物流：通知仓库人员和业务员
            if ("1".equals(cost.getOrderProperty())){
                orderServiceImpl.noticeStorekeeper(cost.getOrderNo());
                noticeInitiator(cost.getOrderNo(),cost.getOrderNo() + "出库物流填写完成！");
            }
        }
        return result;
    }

    /**
     * 通知租赁订单发起人
     *
     * @param orderNo
     */
    private void noticeInitiator(String orderNo,String content) {
        try {
            Order order = orderMapper.selectOrderByOrderNo(orderNo);
            if (Objects.nonNull(order)) {
                List<String> userIds = jpushMapper.selectRegistrationIdsByUserIds(Collections.singletonList(order.getSponsor()));
                if (CollectionUtils.isEmpty(userIds)) {
                    throw new BaseException("通知租赁订单发起人发起人设备不存在"+order.getSponsor());
                }else{
                    UniJpushUtils.doPost(new UniPushDomain(userIds, "湿云", content));
                }
            }else{
                throw new BaseException("通知租赁订单发起人:",orderNo+"订单不存在");
            }
        } catch (Exception e) {
            LOGGER.error("回货物流填写完成通知租赁订单发起人失败", e);
        }
    }

    /**
     * 把物流费用加到对应的出库单子单中
     *
     * @param cost
     * @return 结果
     */
    void updateLogisticsExpenses(LogisticsCost cost) {
        // 把物流费用加到对应的出库单子单中，同时给子单状态赋1
        OutboundOrder outboundOrder = new OutboundOrder();
        outboundOrder.setOutboundNo(cost.getOutboundNo());
        List<OutboundOrder> outboundOrderList = outboundOrderMapper.selectOutboundOrderList(outboundOrder);
        OutboundOrder outboundOrder2 = outboundOrderList.get(outboundOrderList.size() - 1);// 因为字段做了模糊搜索和倒序查询，所以要查最后一个值
        // 类型转换
        String expenses = cost.getLogisticsExpenses();
        BigDecimal logisticsExpenses = new BigDecimal(expenses);
        outboundOrder2.setLogisticsExpenses(logisticsExpenses);
        outboundOrder2.setExpensesStatus("1");
        outboundOrderMapper.updateOutboundOrder(outboundOrder2);
        // 给父单状态赋1
        OutboundOrder outboundOrder6 = new OutboundOrder();
        outboundOrder6.setOrderNo(cost.getOrderNo());
        outboundOrder6.setParentId(0L);
        List<OutboundOrder> outboundOrderList4 = outboundOrderMapper.selectOutboundOrderList(outboundOrder6);
        OutboundOrder outboundOrder7 = outboundOrderList4.get(0);
        // 出库单父单物流费用状态赋"1"
        outboundOrder7.setExpensesStatus("1");
        outboundOrderMapper.updateOutboundOrder(outboundOrder7);

    }

    /**
     * 判断出库单是否已填完物流费用，并给父出库单相应的状态
     *
     * @param cost
     * @return 结果
     */
    void updateExpensesStatus(LogisticsCost cost) {
        OutboundOrder outboundOrder3 = new OutboundOrder();
        outboundOrder3.setOrderNo(cost.getOrderNo());
        List<OutboundOrder> outboundOrderList2 = outboundOrderMapper.selectOutboundOrderList(outboundOrder3);
        outboundOrderList2.forEach(outbound -> {
            // 如果出库单子单未填物流费用
            if (!outbound.getParentId().equals(0L) && outbound.getLogisticsExpenses() == null) {
                OutboundOrder outboundOrder4 = new OutboundOrder();
                outboundOrder4.setOrderNo(outbound.getOrderNo());
                outboundOrder4.setParentId(0L);
                List<OutboundOrder> outboundOrderList3 = outboundOrderMapper.selectOutboundOrderList(outboundOrder4);
                OutboundOrder outboundOrder5 = outboundOrderList3.get(0);
                // 出库单父单物流费用状态赋"2"
                outboundOrder5.setExpensesStatus("2");
                outboundOrderMapper.updateOutboundOrder(outboundOrder5);
            }
            //            //出库单子单物流费用全部填完了
            //            if(!outbound.getParentId().equals(0L) && outbound.getLogisticsExpenses() != null){
            //                OutboundOrder outboundOrder6 = new OutboundOrder();
            //                outboundOrder6.setOrderNo(outbound.getOrderNo());
            //                outboundOrder6.setParentId(0L);
            //                List<OutboundOrder> outboundOrderList4 = outboundOrderMapper.selectOutboundOrderList(outboundOrder6);
            //                OutboundOrder outboundOrder7 = outboundOrderList4.get(0);
            //                //出库单父单物流费用状态赋"1"
            //                outboundOrder7.setExpensesStatus("1");
            //                outboundOrderMapper.updateOutboundOrder(outboundOrder7);
            //                }
        });
    }


    /**
     * 得到更改父单物流状态（先填物流，再添出库单）
     *
     * @param cost
     * @return 结果
     */
    void checkLogisticsStatus(LogisticsCost cost) {
        if (cost.getOrderId() != null) {

            int costSum = 0;

            // 该订单出库物流条数
            LogisticsCost logisticsCost = new LogisticsCost();
            logisticsCost.setOrderId(cost.getOrderId());
            List<LogisticsCost> logisticsCostList = new ArrayList<>();
            List<LogisticsCost> logisticsCostList2 = logisticsCostMapper.selectLogisticsCostList(logisticsCost);
            if (!CollectionUtils.isEmpty(logisticsCostList2)) {// 过滤入库申请物流
                logisticsCostList2.forEach(logistics -> {
                    if (logistics.getReturnApplyNo() == null || logistics.getReturnApplyNo().equals("")) {
                        logisticsCostList.add(logistics);
                    }
                });
            }
            if (!CollectionUtils.isEmpty(logisticsCostList)) {
                // 去重
                List<LogisticsCost> list3 = logisticsCostList.stream().collect(
                        Collectors.collectingAndThen(Collectors.toCollection(
                                () -> new TreeSet<>(Comparator.comparing(LogisticsCost::getSerialNumber))), ArrayList::new));

                costSum = list3.size();
            } else {
                costSum = logisticsCostList.size();
            }


            // 出库单父单和子单条数
            OutboundOrder outboundOrder = new OutboundOrder();
            outboundOrder.setOrderId(cost.getOrderId());
            List<OutboundOrder> list = outboundOrderMapper.selectOutboundOrderList(outboundOrder);
            List<OutboundOrder> list2 = new ArrayList<>();
            // 父单
            outboundOrder.setParentId(0L);
            List<OutboundOrder> list1 = outboundOrderMapper.selectOutboundOrderList(outboundOrder);
            if (!CollectionUtils.isEmpty(list1)) {

                OutboundOrder outboundOrder1 = list1.get(0);
                // 筛选出子单
                if (!CollectionUtils.isEmpty(list)) {
                    list.forEach(or -> {
                        if (or.getParentId() != 0L) {
                            list2.add(or);
                        }
                    });
                }
                // 出库子单条数
                int outSum = list2.size();

                // 根据情况给父出库单赋物流填写状态状态
                if (costSum >= outSum) {
                    outboundOrder1.setExpensesStatus("1");// 已完全填写物流
                    outboundOrderMapper.updateOutboundOrder(outboundOrder1);
                }
                if (costSum < outSum) {
                    outboundOrder1.setExpensesStatus("2");// 未完全填写物流
                    outboundOrderMapper.updateOutboundOrder(outboundOrder1);
                }
            }
        }
    }


    /**
     * 得到产品数量，更改出库单父单物流状态（先填物流，再添出库单）
     *
     * @param cost
     * @return 结果
     */
    void checkLogisticsStatus2(LogisticsCost cost) {
        if (cost.getOrderId() != null) {

            Long orderQuantity = 0L;// 订单产品数量

            Long costQuantity = 0L;// 物流产品数量

            // 获取订单中所有的产品数量
            OrderProduct orderProduct = new OrderProduct();
            orderProduct.setOrderId(cost.getOrderId());
            List<OrderProduct> orderProductList = orderProductMapper.selectOrderProductList(orderProduct);
            // 如果订单产品不为空
            if (!CollectionUtils.isEmpty(orderProductList)) {
                orderQuantity = orderProductList.stream().mapToLong(OrderProduct::getQuantity).sum();
            }

            // 该订单所有出库物流产品
            List<LogisticsProduct> productList = new ArrayList<>();
            // 找到所有出库物流
            LogisticsCost logisticsCost1 = new LogisticsCost();
            logisticsCost1.setOrderProperty("1");
            logisticsCost1.setOrderId(cost.getOrderId());
            List<LogisticsCost> logisticsCostList = logisticsCostMapper.selectLogisticsCostList(logisticsCost1);
            if (!CollectionUtils.isEmpty(logisticsCostList)) {
                logisticsCostList.forEach(logisticsCost -> {
                    // 如果物流不为空，找到每个物流对应的产品
                    LogisticsProduct logisticsProduct = new LogisticsProduct();
                    logisticsProduct.setLogisticsId(logisticsCost.getId());
                    List<LogisticsProduct> LogisticsProductList = logisticsProductMapper.selectLogisticsProductList(logisticsProduct);
                    // 如果物流产品不为空，获取该单所有的物流产品
                    if (!CollectionUtils.isEmpty(LogisticsProductList)) {
                        productList.addAll(LogisticsProductList);
                    }
                });
            }
            if (!CollectionUtils.isEmpty(productList)) {
                costQuantity = productList.stream().mapToLong(LogisticsProduct::getQuantity).sum();
            }

            // 找到出库单父单
            OutboundOrder outboundOrder = new OutboundOrder();
            outboundOrder.setOrderId(cost.getOrderId());
            outboundOrder.setParentId(0L);
            List<OutboundOrder> outboundOrderList = outboundOrderMapper.selectOutboundOrderList(outboundOrder);// 只有一条
            OutboundOrder outboundOrder1 = outboundOrderList.get(0);// 父单

            if (orderQuantity.equals(costQuantity)) {
                outboundOrder1.setExpensesStatus("1");// 物流已完成
            } else {
                outboundOrder1.setExpensesStatus("2");// 物流未完成
            }
            outboundOrderMapper.updateOutboundOrder(outboundOrder1);// 修改父单物流填写状态
        }
    }


    /**
     * 得到产品数量，更改调拨单物流状态
     *
     * @param cost
     * @return 结果
     */
    void checkTransferStatus(LogisticsCost cost) {
        // 此时OrderId传的是调拨单id
        if (cost.getOrderId() != null) {

            Long transferQuantity = 0L;// 调拨单产品数量

            Long costQuantity = 0L;// 物流产品数量

            // 查出对应调拨单,并拿到对应的调拨产品总数
            SyTransferT transfer = syTransferTMapper.selectSyTransferTById(cost.getOrderId());
            if (transfer != null) {// 存在改调拨单
                SyTransferProductT transferProduct = new SyTransferProductT();
                transferProduct.setTransferNo(transfer.getSerialNum());
                List<SyTransferProductT> transferProductTList = syTransferProductMapper.selectSyTransferProductTList(transferProduct);
                if (!CollectionUtils.isEmpty(transferProductTList)) {
                    transferQuantity = transferProductTList.stream().mapToLong(SyTransferProductT::getQuantity).sum();
                }
                // 该调拨单所有调拨物流产品
                List<LogisticsProduct> productList = new ArrayList<>();
                // 找到对应的调拨单物流
                LogisticsCost logisticsCost1 = new LogisticsCost();
                logisticsCost1.setOrderProperty("3");
                logisticsCost1.setOrderId(cost.getOrderId());
                List<LogisticsCost> logisticsCostList = logisticsCostMapper.selectLogisticsCostList(logisticsCost1);
                if (!CollectionUtils.isEmpty(logisticsCostList)) {
                    logisticsCostList.forEach(logisticsCost -> {
                        // 如果物流不为空，找到每个物流对应的产品
                        LogisticsProduct logisticsProduct = new LogisticsProduct();
                        logisticsProduct.setLogisticsId(logisticsCost.getId());
                        List<LogisticsProduct> LogisticsProductList = logisticsProductMapper.selectLogisticsProductList(logisticsProduct);
                        // 如果物流产品不为空，获取该单所有的物流产品
                        if (!CollectionUtils.isEmpty(LogisticsProductList)) {
                            productList.addAll(LogisticsProductList);
                        }
                    });
                }
                if (!CollectionUtils.isEmpty(productList)) {
                    costQuantity = productList.stream().mapToLong(LogisticsProduct::getQuantity).sum();
                }

                if (transferQuantity.equals(costQuantity)) {
                    transfer.setLogisticsStatus("1");// 物流已完成
                } else {
                    transfer.setLogisticsStatus("2");// 物流未完成
                }
                syTransferTMapper.updateSyTransferT(transfer);// 修改调拨单物流状态
            }
        }
    }

    /**
     * 校验产品数量，更改回库申请单和子单父单物流状态
     *
     * @param cost
     * @return 结果
     */
    void checkReturnApplyStatus2(LogisticsCost cost) {
        if (cost.getOrderId() != null) {

            Long costQuantity = 0L;// 回货物流产品总数量

            Long returnQuantity = 0L;// 回货产品产品总数量

            // 该订单所有回货物流产品
            List<LogisticsProduct> productList = new ArrayList<>();
            // 找到订单所有回货物流
            LogisticsCost logisticsCost1 = new LogisticsCost();
            logisticsCost1.setOrderProperty("2");
            logisticsCost1.setOrderId(cost.getOrderId());
            List<LogisticsCost> logisticsCostList = logisticsCostMapper.selectLogisticsCostList(logisticsCost1);
            if (!CollectionUtils.isEmpty(logisticsCostList)) {
                logisticsCostList.forEach(logisticsCost -> {
                    // 如果物流不为空，找到每个物流对应的产品
                    LogisticsProduct logisticsProduct = new LogisticsProduct();
                    logisticsProduct.setLogisticsId(logisticsCost.getId());
                    List<LogisticsProduct> LogisticsProductList = logisticsProductMapper.selectLogisticsProductList(logisticsProduct);
                    // 如果物流产品不为空，获取该单所有的物流产品
                    if (!CollectionUtils.isEmpty(LogisticsProductList)) {
                        productList.addAll(LogisticsProductList);
                    }
                });
            }
            if (!CollectionUtils.isEmpty(productList)) {
                costQuantity = productList.stream().mapToLong(LogisticsProduct::getQuantity).sum();
            }
            // 该订单所有回货申请产品
            List<ReturnApplyProduct> productList2 = new ArrayList<>();
            // 找到订单所有回货申请(包括父单和子单）
            ReturnApplyDto returnApply = new ReturnApplyDto();
            returnApply.setOrderId(cost.getOrderId());
            List<ReturnApplyDto> returnApplyList = returnApplyMapper.selectReturnApplyList(returnApply);
            if (!CollectionUtils.isEmpty(returnApplyList)) {
                returnApplyList.forEach(apply -> {
                    if (apply.getParentId() != 0L) {// 子单有产品
                        // 如果回货申请不为空，找到每个回货申请子单对应的产品
                        ReturnApplyProduct returnApplyProduct = new ReturnApplyProduct();
                        returnApplyProduct.setReturnApplyId(apply.getId());
                        List<ReturnApplyProduct> returnApplyProductList = returnApplyProductMapper.selectReturnApplyProductList(returnApplyProduct);

                        // 如果回货申请产品不为空，比较修改子单状态，获取该单所有的回货申请产品
                        List<LogisticsProduct> productList3 = new ArrayList<>();
                        if (!CollectionUtils.isEmpty(returnApplyProductList)) {
                            // 回货申请子单产品数量
                            Long returnQuantity1 = returnApplyProductList.stream().mapToLong(ReturnApplyProduct::getReturnQuantity).sum();

                            // 找到回货申请子单所有回货物流产品数量
                            LogisticsCost logisticsCost2 = new LogisticsCost();
                            logisticsCost2.setOrderProperty("2");
                            logisticsCost2.setOrderId(apply.getOrderId());
                            logisticsCost2.setReturnApplyNo(apply.getReturnApplyNo());
                            List<LogisticsCost> logisticsCostList2 = logisticsCostMapper.selectLogisticsCostList(logisticsCost2);
                            if (!CollectionUtils.isEmpty(logisticsCostList2)) {
                                logisticsCostList2.forEach(logisticsCost -> {
                                    // 如果物流不为空，找到每个物流对应的产品
                                    LogisticsProduct logisticsProduct3 = new LogisticsProduct();
                                    logisticsProduct3.setLogisticsId(logisticsCost.getId());
                                    List<LogisticsProduct> LogisticsProductList3 = logisticsProductMapper.selectLogisticsProductList(logisticsProduct3);
                                    // 如果物流产品不为空，获取该子单所有的物流产品
                                    if (!CollectionUtils.isEmpty(LogisticsProductList3)) {
                                        productList3.addAll(LogisticsProductList3);
                                    }
                                });
                                if (!CollectionUtils.isEmpty(productList3)) {
                                    Long costQuantity1 = productList3.stream().mapToLong(LogisticsProduct::getQuantity).sum();
                                    if (costQuantity1.equals(returnQuantity1)) {
                                        apply.setExpensesStatus("1");// 物流已完成
                                    } else {
                                        apply.setExpensesStatus("2");// 物流未完成
                                    }
                                    returnApplyMapper.updateReturnApply(apply);
                                }
                            }
                            productList2.addAll(returnApplyProductList);
                        }
                    }
                });
            }

            if (!CollectionUtils.isEmpty(productList2)) {
                returnQuantity = productList2.stream().mapToLong(ReturnApplyProduct::getReturnQuantity).sum();
            }

            // 拿到回货申请父单
            ReturnApplyDto returnApply1 = new ReturnApplyDto();
            returnApply1.setOrderId(cost.getOrderId());
            returnApply1.setParentId(0L);
            List<ReturnApplyDto> returnApplyList1 = returnApplyMapper.selectReturnApplyList(returnApply1);
            ReturnApplyDto returnApply2 = returnApplyList1.get(0);
            if (returnQuantity.equals(costQuantity)) {
                returnApply2.setExpensesStatus("1");// 物流已完成
            } else {
                returnApply2.setExpensesStatus("2");// 物流未完成
            }
            returnApplyMapper.updateReturnApply(returnApply2);// 修改父单物流填写状态
        }
    }

    /**
     * 出库机器加物流到达时间
     *
     * @param cost
     * @return 结果
     */
    void updateOutMachineTime(LogisticsCost cost) {
        if (cost.getOutboundNo() != null) {
            OutboundOrder outboundOrder = new OutboundOrder();
            outboundOrder.setOutboundNo(cost.getOutboundNo());// 物流表只有子单编号
            List<OutboundOrder> list = outboundOrderMapper.selectOutboundOrderList(outboundOrder);
            if (!CollectionUtils.isEmpty(list)) {
                OutboundOrder outboundOrder1 = list.get(0);// 一个子单编号对应一个出库单子单
                if (cost.getArrivalDate() != null) {
                    OutboundOrderMachine outboundOrderMachine = new OutboundOrderMachine();
                    outboundOrderMachine.setOutboundOrderId(outboundOrder1.getId());
                    // 查出所有出库机器数据，加上时间
                    List<OutboundOrderMachine> list2 = outboundOrderMachineMapper.selectOutboundOrderMachineList(outboundOrderMachine);
                    if (!CollectionUtils.isEmpty(list2)) {
                        list2.forEach(machine -> {
                            machine.setLogisticsTime(cost.getArrivalDate());
                            outboundOrderMachineMapper.updateOutboundOrderMachine(machine);
                        });
                    }
                }
            }
        }
    }


    /**
     * 物流增加物流产品
     *
     * @param cost
     * @return 结果
     */
    //    @Transactional(rollbackFor = Exception.class)
    void insertLogisticsCostProduct(LogisticsCost cost) {
        cost.getLogisticsProductList().forEach(product -> {
            product.setLogisticsId(cost.getId());
            product.setOrderProperty(cost.getOrderProperty());
            logisticsProductMapper.insertLogisticsProduct(product);
        });

        //        try {
        //            //物流增加物流产品
        //            insertLogisticsCostProduct(cost);
        //        } catch (Exception e) {
        //            throw new RuntimeException(e);
        //        }
    }


    /**
     * 物流增加出库单编号
     *
     * @param cost
     * @return 结果
     */
    void insertOutboundNo(LogisticsCost cost) {

        // 该订单子出库单集合
        OutboundOrder outboundOrder1 = new OutboundOrder();
        outboundOrder1.setOrderId(cost.getOrderId());
        List<OutboundOrder> list2 = new ArrayList<>();
        List<OutboundOrder> list = outboundOrderMapper.selectOutboundOrderList(outboundOrder1);
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(or -> {
                if (or.getParentId() != 0L) {
                    list2.add(or);
                }
            });
        }

        if (!CollectionUtils.isEmpty(list2)) {
            list2.forEach(outboundOrder -> {
                // 截取出库单子单编号中相应的数字（物流绑定子单）
                String str1 = outboundOrder.getOutboundNo().substring(0, outboundOrder.getOutboundNo().indexOf("-"));
                String number = outboundOrder.getOutboundNo().substring(str1.length() + 1);

                if (cost.getSerialNumber().equals(number)) {
                    cost.setOutboundNo(outboundOrder.getOutboundNo());
                    //                    logisticsCostMapper.updateLogisticsCost(cost);
                }
            });
        }
    }

    /**
     * 修改物流时增加出库单编号
     *
     * @param cost
     * @return 结果
     */
    void updateOutboundNo(LogisticsCost cost) {

        // 该订单子出库单集合
        OutboundOrder outboundOrder1 = new OutboundOrder();
        outboundOrder1.setOrderId(cost.getOrderId());
        List<OutboundOrder> list2 = new ArrayList<>();
        List<OutboundOrder> list = outboundOrderMapper.selectOutboundOrderList(outboundOrder1);
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(or -> {
                if (or.getParentId() != 0L) {
                    list2.add(or);
                }
            });
        }

        if (!CollectionUtils.isEmpty(list2)) {
            list2.forEach(outboundOrder -> {
                // 截取出库单子单编号中相应的数字（物流绑定子单）
                String str1 = outboundOrder.getOutboundNo().substring(0, outboundOrder.getOutboundNo().indexOf("-"));
                String number = outboundOrder.getOutboundNo().substring(str1.length() + 1);

                if (cost.getSerialNumber().equals(number)) {
                    cost.setOutboundNo(outboundOrder.getOutboundNo());
                    logisticsCostMapper.updateLogisticsCost(cost);
                }
            });
        }
    }


    /**
     * 把物流费用加到对应的入库申请单子单中
     *
     * @param cost
     * @return 结果
     */
    void updateReturnApply(LogisticsCost cost) {
        if (cost.getLogisticsExpenses() != null) {
            // 把物流费用加到对应的入库申请单子单中，同时给子单状态赋1
            ReturnApply returnApply = new ReturnApply();
            returnApply.setReturnApplyNo(cost.getReturnApplyNo());
            List<ReturnApplyDto> returnApplyList = returnApplyMapper.selectReturnApplyList(returnApply);
            ReturnApply returnApply2 = returnApplyList.get(0);
            // 类型转换
            String expenses = cost.getLogisticsExpenses();
            BigDecimal logisticsExpenses = new BigDecimal(expenses);
            returnApply2.setLogisticsExpenses(logisticsExpenses);
            returnApply2.setExpensesStatus("1");
            returnApplyMapper.updateReturnApply(returnApply2);

            ReturnApply returnApply6 = new ReturnApply();
            returnApply6.setOrderNo(cost.getOrderNo());
            returnApply6.setParentId(0L);
            List<ReturnApplyDto> returnApplyList4 = returnApplyMapper.selectReturnApplyList(returnApply6);
            ReturnApply returnApply7 = returnApplyList4.get(0);
            // 回库申请单父单物流费用状态赋"1"
            returnApply7.setExpensesStatus("1");
            returnApplyMapper.updateReturnApply(returnApply7);
        }
    }

    /**
     * 判断入库申请单是否已填完物流费用，并给父出库单相应的状态
     *
     * @param cost
     * @return 结果
     */
    void updateReturnApplyStatus(LogisticsCost cost) {
        ReturnApply returnApply3 = new ReturnApply();
        returnApply3.setOrderNo(cost.getOrderNo());
        List<ReturnApplyDto> returnApplyList2 = returnApplyMapper.selectReturnApplyList(returnApply3);
        returnApplyList2.forEach(returnApply -> {
            // 如果入库申请单子单未填物流费用
            if (!returnApply.getParentId().equals(0L) && returnApply.getLogisticsExpenses() == null) {
                ReturnApply returnApply4 = new ReturnApply();
                returnApply4.setOrderNo(returnApply.getOrderNo());
                returnApply4.setParentId(0L);
                List<ReturnApplyDto> returnApplyList3 = returnApplyMapper.selectReturnApplyList(returnApply4);
                ReturnApply returnApply5 = returnApplyList3.get(0);
                // 入库单父单物流费用状态赋"2"
                returnApply5.setExpensesStatus("2");
                returnApplyMapper.updateReturnApply(returnApply5);
            }
            //            //入库单子单物流费用全部填完了
            //            else{
            //                ReturnApply returnApply6 = new ReturnApply();
            //                returnApply6.setOrderNo(returnApply.getOrderNo());
            //                returnApply6.setParentId(0L);
            //                List<ReturnApplyDto> returnApplyList4 = returnApplyMapper.selectReturnApplyList(returnApply6);
            //                ReturnApply returnApply7 = returnApplyList4.get(0);
            //                //出库单父单物流费用状态赋"1"
            //                returnApply7.setExpensesStatus("1");
            //                returnApplyMapper.updateReturnApply(returnApply7);
            //                }
        });
    }

    /**
     * 修改物流费用数据
     *
     * @param cost
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateLogisticsCost(LogisticsCost cost) {
        SysUser sysUser = sysUserService.selectUserByUserName(SecurityUtils.getUsername());
        cost.setUpdateBy(sysUser.getUserName());
        cost.setUpdateTime(DateUtils.getNowDate());

        // 回货申请物流增加物流产品
        if ((cost.getOrderProperty().equals("1"))) {
            // 根据orderNo校验更改父单物流状态（先填物流，再填出库单）
            // checkLogisticsStatus(cost);

            if (!CollectionUtils.isEmpty(cost.getLogisticsProductList())) {

                logisticsProductMapper.deleteLogisticsProductByLogisticsId(cost.getId());
                // 出库物流增加物流产品
                insertLogisticsCostProduct(cost);
            }
            checkLogisticsStatus2(cost);

            // 物流增加出库单子单编号
            // updateOutboundNo(cost);

            // 如果填了物流到达时间，则出库机器加物流到达时间
            if (cost.getArrivalDate() != null) {
                updateOutMachineTime(cost);
                //到货时间填写完成通知业务员
                noticeInitiatorAfterArrivalDate(cost);
            }

        } else if (cost.getOrderProperty().equals("2")) {

            if (!CollectionUtils.isEmpty(cost.getLogisticsProductList())) {

                logisticsProductMapper.deleteLogisticsProductByLogisticsId(cost.getId());
                // 出库物流增加物流产品
                insertLogisticsCostProduct(cost);
            }

            // 获取产品数量，更改回库申请单和子单父单物流状态
            checkReturnApplyStatus2(cost);
            // 把物流费用加到对应的入库申请单子单中
            // updateReturnApply(cost);
            // 判断出库单子单是否已填完物流费用，并给父入库申请单添加相应的状态
            // updateReturnApplyStatus(cost);
        } else {
            if ((cost.getOrderProperty().equals("3"))) {

                if (!CollectionUtils.isEmpty(cost.getLogisticsProductList())) {

                    logisticsProductMapper.deleteLogisticsProductByLogisticsId(cost.getId());
                    // 出库物流增加物流产品
                    insertLogisticsCostProduct(cost);
                }

                // 校验产品数量，更改回库申请单和子单父单物流状态
                checkTransferStatus(cost);
            }
        }
        return logisticsCostMapper.updateLogisticsCost(cost);
    }

    /**
     * 到货时间填写完成通知业务员
     * @param cost
     */
    private void noticeInitiatorAfterArrivalDate(LogisticsCost cost) {
        try {
            //到货时间填写完成通知业务员
            LogisticsCost logisticsCost = logisticsCostMapper.selectLogisticsCostById(cost.getId().toString());
            if (Objects.isNull(logisticsCost)){
                throw new BaseException("到货时间填写完成通知业务员-查询物流信息为空");
            }
            Date arrivalDate = logisticsCost.getArrivalDate();
            LOGGER.info("到货时间填写完成通知业务员-到货时间："+arrivalDate);
            if (arrivalDate==null){
                // 通知业务员
                noticeInitiator(logisticsCost.getOrderNo(),logisticsCost.getOrderNo()+"订单已到货。");
            }
        } catch (Exception e) {
            LOGGER.error("到货时间填写完成通知业务员失败");
        }
    }


    /**
     * 删除物流费用数据
     *
     * @param id 物流费用主键
     * @return 结果
     */
    @Override
    public int deleteLogisticsCostById(String id) {
        return logisticsCostMapper.deleteLogisticsCostById(id);
    }

    /**
     * 批量删除物流费用
     *
     * @param ids 需要删除的主键
     * @return 结果
     */
    @Override
    public int deleteLogisticsCostByIds(String[] ids) {
        return logisticsCostMapper.deleteLogisticsCostByIds(ids);
    }


//    add

    /**
     * 查询物流费用或到货日期为空的物流
     *
     * @param
     * @return 物流费用
     */
    @Override
    public List<LogisticsCost> selectLogisticsCostByExpensesORArrivalDateOut(LogisticsCost cost) {
        List<LogisticsCost> list = logisticsCostMapper.selectLogisticsCostByExpensesORArrivalDateOut(cost);
        return list;
    }

    /**
     * 查询物流费用或到货日期为空的入库物流
     *
     * @param
     * @return 物流费用
     */
    @Override
    public List<LogisticsCost> selectLogisticsCostByExpensesORArrivalDateIn(LogisticsCost cost) {
        List<LogisticsCost> list = logisticsCostMapper.selectLogisticsCostByExpensesORArrivalDateIn(cost);
        return list;
    }

    /**
     * 返回物流费用或到货日期为空的入库物流单号
     *
     * @param
     * @return 物流费用
     */
    @Override
    public List<LogisticsCost> selectLogisticsCostByExpensesORArrivalDateTransfer(LogisticsCost cost) {
        List<LogisticsCost> list = logisticsCostMapper.selectLogisticsCostByExpensesORArrivalDateTransfer(cost);
        return list;
    }

    /**
     * 返回物流费用或到货日期为空的出库物流单号
     *
     * @param
     * @return 物流费用
     */
    @Override
    public String[] GetAllOutboundNo() {
        LogisticsCost cost = new LogisticsCost();
        List<LogisticsCost> list = logisticsCostMapper.selectLogisticsCostByExpensesORArrivalDateOut(cost);
        String[] oubundno;
        if (list.size() == 0) {
            oubundno = new String[1];
        } else {
            oubundno = new String[list.size()];
            for (int i = 0; i < list.size(); i++) {
                String no = list.get(i).getOutboundNo();
                oubundno[i] = no.substring(0, no.length() - 2);
            }
        }
        return oubundno;
    }

    /**
     * 返回物流费用或到货日期为空的入库物流单号
     *
     * @param
     * @return 物流费用
     */
    @Override
    public String[] GetAllReturnNo() {
        LogisticsCost cost = new LogisticsCost();
        List<LogisticsCost> list = logisticsCostMapper.selectLogisticsCostByExpensesORArrivalDateIn(cost);
        String[] returnNo;
        if (list.size() == 0) {
            returnNo = new String[1];
        } else {
            returnNo = new String[list.size()];
            for (int i = 0; i < list.size(); i++) {
                String no = list.get(i).getReturnApplyNo();
                returnNo[i] = no.substring(0, no.length() - 2);
            }
        }
        return returnNo;
    }

    /**
     * 返回物流费用或到货日期为空的调拨物流单号
     *
     * @param
     * @return 物流费用
     */
    @Override
    public String[] GetAllTransferNo() {
        LogisticsCost cost = new LogisticsCost();
        List<LogisticsCost> list = logisticsCostMapper.selectLogisticsCostByExpensesORArrivalDateTransfer(cost);
        String[] orderNo;
        if (list.size() == 0) {
            orderNo = new String[1];
        } else {
            orderNo = new String[list.size()];
            for (int i = 0; i < list.size(); i++) {
                orderNo[i] = list.get(i).getOrderNo();
                System.out.println(list.get(i).getOrderNo());
            }
        }
        return orderNo;
    }
//    add
}
